﻿using System.Xml;
using DotNetNuke.Entities.Modules;

namespace DNNToolkit.CrystalReport.Components
{
    public class ConfigController
    {
        public static void CheckToAddConfig(PortalModuleBase moduleBase)
        {
            bool isNeedUpdateConfig = false;

            XmlDocument configDoc = DotNetNuke.Common.Utilities.Config.Load();

            XmlNode httpHandlersNode = configDoc.SelectSingleNode("/configuration/system.web/httpHandlers");

            XmlAttribute pathAtt = CreateAttribute(configDoc, "path", "Reserved.ReportViewerWebControl.axd");
            XmlAttribute verbAtt = CreateAttribute(configDoc, "verb", "*");
            XmlAttribute typeAtt = CreateAttribute(configDoc, "type", "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
            XmlAttribute validateAtt = CreateAttribute(configDoc, "validate", "false");
            XmlNode reportHandlNode = CreateNode(configDoc, "add");

            reportHandlNode.Attributes.Append(pathAtt);
            reportHandlNode.Attributes.Append(verbAtt);
            reportHandlNode.Attributes.Append(typeAtt);
            reportHandlNode.Attributes.Append(validateAtt);

            if (!IsNodeExist(httpHandlersNode, reportHandlNode))
            {
                httpHandlersNode.AppendChild(reportHandlNode);
                isNeedUpdateConfig = true;
            }

            XmlNode assembliesNode = configDoc.SelectSingleNode("/configuration/system.web/compilation/assemblies");

            XmlAttribute assemblyAtt1 = CreateAttribute(configDoc, "assembly", "Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A");
            XmlNode addNode1 = CreateNode(configDoc, "add");
            addNode1.Attributes.Append(assemblyAtt1);

            if (!IsNodeExist(assembliesNode, addNode1))
            {
                assembliesNode.AppendChild(addNode1);
                isNeedUpdateConfig = true;
            }

            XmlAttribute assemblyAtt2 = CreateAttribute(configDoc, "assembly", "Microsoft.ReportViewer.Common, Version=9.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A");
            XmlNode addNode2 = CreateNode(configDoc, "add");
            addNode2.Attributes.Append(assemblyAtt2);

            if (!IsNodeExist(assembliesNode, addNode2))
            {
                assembliesNode.AppendChild(addNode2);
                isNeedUpdateConfig = true;
            }

            XmlNode buildProvidersNode = configDoc.SelectSingleNode("/configuration/system.web/compilation/buildProviders");

            XmlAttribute extensionAtt = CreateAttribute(configDoc, "extension", ".rdlc");
            XmlAttribute buildProvidersTypeAtt = CreateAttribute(configDoc, "type", "Microsoft.Reporting.RdlBuildProvider, Microsoft.ReportViewer.Common, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

            XmlNode buildProviderAddNode = CreateNode(configDoc, "add");
            buildProviderAddNode.Attributes.Append(extensionAtt);
            buildProviderAddNode.Attributes.Append(buildProvidersTypeAtt);

            if (!IsNodeExist(buildProvidersNode, buildProviderAddNode))
            {
                buildProvidersNode.AppendChild(buildProviderAddNode);
                isNeedUpdateConfig = true;
            }

            if (isNeedUpdateConfig)
            {
                DotNetNuke.Common.Utilities.Config.Save(configDoc);
            }
        }

        private static XmlNode CreateNode(XmlDocument doc, string name)
        {
            XmlNode newNode = doc.CreateElement(name);

            return newNode;
        }

        private static XmlAttribute CreateAttribute(XmlDocument doc, string name, string value)
        {
            XmlAttribute newAtt = doc.CreateAttribute(name);

            newAtt.Value = value;

            return newAtt;
        }

        private static bool IsNodeExist(XmlNode parentNode, XmlNode node)
        {
            foreach (XmlNode child in parentNode.ChildNodes)
            {
                if (CompareNode(child, node))
                {
                    return true;
                }
            }
            return false;
        }

        private static bool CompareNode(XmlNode node1, XmlNode node2)
        {
            if (node1.Name != node2.Name)
                return false;

            if (node1.Attributes.Count != node2.Attributes.Count)
                return false;

            foreach (XmlAttribute att1 in node1.Attributes)
            {
                bool isEqual = false;

                foreach (XmlAttribute att2 in node2.Attributes)
                {
                    if (att2.Name.Equals(att1.Name))
                    {
                        if (att1.Value.ToLower().Equals(att2.Value.ToLower()))
                        {
                            isEqual = true;
                            break;
                        }
                    }
                }

                if (!isEqual)
                    return false;
            }

            return true;
        }
    }
}
